package com.bird.system.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 任务状态管理
 *
 * @author: 李涛
 * @version: 2020年09月26日 12:43
 */
@Service
@Slf4j
public class TaskStatusManageService {

	/**
	 * 任务状态，Key任务ID，重入锁
	 */
	private static final Map<Long, ReentrantLock> taskLocker = new ConcurrentHashMap<>();

	/**
	 * 任务状态，Key任务ID，通知唤醒
	 */
	private static final Map<Long, Condition> taskCondition = new ConcurrentHashMap<>();

	/**
	 * 获取锁对象
	 *
	 * @param id 任务ID
	 * @return
	 */
	public ReentrantLock getLocker(Long id) {
		ReentrantLock locker = taskLocker.get(id);
		if (locker == null) {
			locker = new ReentrantLock();
			taskLocker.put(id, locker);
		}
		return locker;
	}


	/**
	 * 开始锁
	 *
	 * @param id 任务ID
	 * @return
	 */
	public boolean tryLock(Long id) {
		ReentrantLock locker = getLocker(id);
		return locker.tryLock();
	}

	/**
	 * 开始锁
	 *
	 * @param id 任务ID
	 * @return
	 */
	public boolean tryLock(Long id, long time) {
		ReentrantLock locker = getLocker(id);
		try {
			return locker.tryLock(time, TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
			return false;
		}
	}

	/**
	 * 开始锁
	 *
	 * @param id 任务ID
	 * @return
	 */
	public void lock(Long id) {
		ReentrantLock locker = getLocker(id);
		locker.lock();
	}

	/**
	 * 取消锁
	 *
	 * @param id 任务ID
	 * @return
	 */
	public void unlock(Long id) {
		ReentrantLock locker = getLocker(id);
		try {
			locker.unlock();
		} catch (Exception e) {

		}
	}


	/**
	 * 获取条件唤醒
	 *
	 * @param id 任务ID
	 * @return
	 */
	public Condition getCondition(Long id) {
		ReentrantLock locker = getLocker(id);
		Condition condition = taskCondition.get(id);
		if (condition == null) {
			condition = locker.newCondition();
			taskCondition.put(id, condition);
		}
		return condition;
	}

	/**
	 * 有信号则暂停
	 *
	 * @param id 任务ID
	 * @return
	 */
	public void pause(Long id) {
		if (taskCondition.get(id) != null) {
			await(id);
		}
	}

	/**
	 * 暂停
	 *
	 * @param id 任务ID
	 * @return
	 */
	public void await(Long id) {
		lock(id);
		log.info("{} 任务暂停执行", id);
		Condition condition = getCondition(id);
		try {
			condition.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		unlock(id);
	}


	/**
	 * 取消暂停
	 *
	 * @param id 任务ID
	 * @return
	 */
	public void signalAll(Long id) {
		lock(id);
		Condition condition = getCondition(id);
		try {
			condition.signalAll();
		} catch (Exception e) {

		}

		log.info("{} 任务恢复执行", id);
		unlock(id);
		taskCondition.remove(id);
	}

	public void removeAll(Long id) {
		taskLocker.remove(id);
		taskCondition.remove(id);
	}

}
